<?php
/**
*
* @package ppkBB3cker
* @version $Id: rannfunc.php 1.000 2010-05-07 11:25:00 PPK $
* @copyright (c) 2010 PPK
* @license http://opensource.org/licenses/gpl-license.php GNU Public License
*
*/

/**
* @ignore
*/
if (!defined('IN_PHPBB'))
{
	exit;
}

function remote_announce($url, $info_hash, $scrape=false)
{
	global $phpEx, $phpbb_root_path, $ppkbb_tcrannounces_options;

	if(ini_get('allow_url_fopen')!=1 || (!function_exists('file_get_contents')/* && !function_exists('fsockopen')*/))
	{
		trigger_error("Remote announces: Sorry, function 'file_get_contents' or 'allow_url_fopen' disabled");
	}

	$a_url = @parse_url($url);
	$scheme = @$a_url['scheme'];
	$host = @$a_url['host'];
	$port = isset($a_url['port']) ? ':'.$a_url['port'] : '';
	$path = @$a_url['path'];

	$q_string = isset($a_url['query']) ? explode('&', $a_url['query']) : array();
	$get_opt=array();

	foreach($q_string as $value)
	{
		@list($q_key, $q_value)=explode('=', $value);
		$get_opt[$q_key] = $q_value;
	}

	$get_opt = array_merge($get_opt, array(
			'peer_id' => urlencode('-UT1820-'.(substr(md5(date('d-m-Y')), 0, 12))),
			'port' => rand(1024, 65535),
			'uploaded' => 0,
			'downloaded' => 0,
			'left' => 1,
			'corrupt' => 0,
			'key' => substr(md5(date('Y-m-d')), 0, 8),
			'event' => 'started',
			'supportcrypto' => 1,
			'numwant' => $ppkbb_tcrannounces_options[2] ? $ppkbb_tcrannounces_options[2] : 50,
			'compact' => 1,
			'no_peer_id' => 1,
			'info_hash' => rawurlencode($info_hash),
			)
	);

	//$query = http_build_query($get_opt);
	$query='';
	$i=0;
	$q=sizeof($get_opt);
	foreach($get_opt as $k => $v)
	{
		$i+=1;
		$query.="{$k}={$v}".($i<$q ? '&' : '');
	}

	if(function_exists('file_get_contents') && in_array($scheme, array('http')))
	{
		$opt = array('http' =>
				array(
					'method' => 'GET',
					'header' => "User-Agent: uTorrent/1820\r\n".
							"Host: {$host}\r\n".
							"Connection: close\r\n",
					'timeout' => $ppkbb_tcrannounces_options[4] ? $ppkbb_tcrannounces_options[4] : 5
				)
		);

		$context = stream_context_create($opt);
		$result = @file_get_contents('http://'.$host.$port.$path.($query ? '?'.$query : ''), false, $context);
	}
	else if($scheme=='udp')
	{
		include_once("{$phpbb_root_path}tracker/include/udptscraper.{$phpEx}");
		try
		{
			$timeout = $ppkbb_tcrannounces_options[4] ? $ppkbb_tcrannounces_options[4] : 5;

			$scraper = new udptscraper($timeout);
			$info_hash2=bin2hex($info_hash);

			$ret = $scraper->scrape("udp://".$host.$port.$path.($query ? '?'.$query : ''), array($info_hash2));

			$result=array(
				'interval' => 0,
				'seeders' => my_int_val(@$ret[$info_hash2]['seeders']),
				'leechers' => my_int_val(@$ret[$info_hash2]['leechers']),
				'times_completed' => my_int_val(@$ret[$info_hash2]['completed']),
				'peers' => my_int_val(@$ret[$info_hash2]['seeders']+@$ret[$info_hash2]['leechers']),
				'a_message'=> '',
			);

			return $result;
		}
		catch(ScraperException $e)
		{
			return array('a_message' => 'UDP announce error: '.$e->getMessage().($e->isConnectionError() ? ' (connection error)' : ''));
		}
		//return array('a_message' => 'UDP announce not supported');
	}

	if(!$result)
	{
		return array('a_message' => 'Query timeout');
	}

	include_once($phpbb_root_path.'tracker/include/bencoding.'.$phpEx);
	$result = bdecode($result);

	if(!is_array($result))
	{
		return array('a_message' => 'BDecoding error');
	}

	$result['complete']=my_int_val(@$result['complete']);
	$result['incomplete']=my_int_val(@$result['incomplete']);
	//$result['bin_peers']=unpack("C*", @$result['peers']);
	/*if(is_array($result['bin_peers']) && sizeof($result['bin_peers']))
	{
		$result['peers']=sizeof($result['bin_peers'])/6;
	}
	else
	{*/
		if(@$result['peers'] && !is_array($result['peers']))
		{
			$result['peers']=strlen($result['peers'])/6;
		}
		else
		{
			@$result['peers'] ? $result['peers']=sizeof($result['peers']) : $result['peers']=0;
		}
	//}
	if($result['peers'] && $result['complete']+$result['incomplete']==0)
	{
		!$ppkbb_tcrannounces_options[3] || $ppkbb_tcrannounces_options[3] > 100 ? $ppkbb_tcrannounces_options[3]=100 : '';
		$result['complete']=my_int_val($ppkbb_tcrannounces_options[3]*$result['peers']/100);
		$result['incomplete']=$result['peers']-$result['complete'];
	}
	else
	{
		$result['peers']=$result['complete']+$result['incomplete'];
	}

	$return=array(
		'interval' => my_int_val(@$result['interval']),
		'seeders' => my_int_val(@$result['complete']),
		'leechers' => my_int_val(@$result['incomplete']),
		'times_completed' => my_int_val(@$result['downloaded']),
		'peers' => my_int_val(@$result['peers']),
		'a_message'=> @$result['failure reason'] ? utf8_normalize_nfc($result['failure reason']) : '',
		//'bin_peers' => @$result['bin_peers'],
	);
	$scrape ? $return['s_message']='Scrape not supported' : '';

	return $return;

}

function remote_scrape($url, $info_hash)
{
	global $phpEx, $phpbb_root_path, $ppkbb_tcrannounces_options;

	if(ini_get('allow_url_fopen')!=1 || (!function_exists('file_get_contents')/* && !function_exists('fsockopen')*/))
	{
		trigger_error("Remote announces: Sorry, function 'file_get_contents' or 'allow_url_fopen' disabled");
	}

	$url2=str_replace('announce', 'scrape', $url);

	if($ppkbb_tcrannounces_options[7]/* || $url2==$url*/)
	{
		return remote_announce($url, $info_hash, true);
	}
	$url=$url2;

	$a_url = @parse_url($url);
	$scheme = @$a_url['scheme'];
	$host = @$a_url['host'];
	$port = isset($a_url['port']) ? ':'.$a_url['port'] : '';
	$path = @$a_url['path'];

	$q_string = isset($a_url['query']) ? explode('&', $a_url['query']) : array();
	$get_opt=array();

	foreach($q_string as $value)
	{
		@list($q_key, $q_value)=explode('=', $value);
		$get_opt[$q_key] = $q_value;
	}

	$get_opt = array_merge($get_opt, array(
			'info_hash' => rawurlencode($info_hash),
		)
	);

	//$query = http_build_query($get_opt);
	$query='';
	$i=0;
	$q=sizeof($get_opt);
	foreach($get_opt as $k => $v)
	{
		$i+=1;
		$query.="{$k}={$v}".($i<$q ? '&' : '');
	}

	$opt = array('http' =>
			array(
				'method' => 'GET',
				'header' => "User-Agent: uTorrent/1820\r\n".
						"Host: {$host}\r\n".
						"Connection: close\r\n",
				'timeout' => $ppkbb_tcrannounces_options[4] ? $ppkbb_tcrannounces_options[4] : 5
			)
	);

	if(function_exists('file_get_contents') && in_array($scheme, array('http')))
	{
		$context = @stream_context_create($opt);
		$result = @file_get_contents('http://'.$host.$port.$path.($query ? '?'.$query : ''), false, $context);
	}
	else if($scheme=='udp')
	{
		include_once("{$phpbb_root_path}tracker/include/udptscraper.{$phpEx}");
		try
		{
			$timeout = $ppkbb_tcrannounces_options[4] ? $ppkbb_tcrannounces_options[4] : 5;

			$scraper = new udptscraper($timeout);
			$info_hash2=bin2hex($info_hash);

			$ret = $scraper->scrape("udp://".$host.$port.$path.($query ? '?'.$query : ''), array($info_hash2));

			$result=array(
				'interval' => 0,
				'seeders' => my_int_val(@$ret[$info_hash2]['seeders']),
				'leechers' => my_int_val(@$ret[$info_hash2]['leechers']),
				'times_completed' => my_int_val(@$ret[$info_hash2]['completed']),
				'peers' => my_int_val(@$ret[$info_hash2]['seeders']+@$ret[$info_hash2]['leechers']),
				's_message'=> '',
			);

			return $result;
		}
		catch(ScraperException $e)
		{
			return array('s_message' => 'UDP scrape error: '.$e->getMessage().($e->isConnectionError() ? ' (connection error)' : ''));
		}
	}

	if(!$result)
	{
		return array('s_message' => 'Query timeout');
	}

	include_once($phpbb_root_path.'tracker/include/bencoding.'.$phpEx);
	$result = bdecode($result);

	if(!is_array($result))
	{
		return array('s_message' => 'BDecoding error');
	}

	if(!@$result['failure reason'] && !isset($result['files'][$info_hash]['complete']) && !isset($result['files'][$info_hash]['incomplete']) && !isset($result['files'][$info_hash]['downloaded']))
	{
		return array('s_message' => 'Empty result');
	}

	return array(
		'interval' => my_int_val(@$result['flags']['min_request_interval']),
		'seeders' => my_int_val(@$result['files'][$info_hash]['complete']),
		'leechers' => my_int_val(@$result['files'][$info_hash]['incomplete']),
		'times_completed' => my_int_val(@$result['files'][$info_hash]['downloaded']),
		'peers' => my_int_val(@$result['files'][$info_hash]['complete']+@$result['files'][$info_hash]['incomplete']),
		's_message'=> @$result['failure reason'] ? utf8_normalize_nfc($result['failure reason']) : '',
	);

}
?>
